import { useCallback, RefObject, useRef } from 'react';
import { findNodeHandle } from 'react-native';
import { useSharedValue, SharedValue } from 'react-native-reanimated';
import { SCROLLABLE_STATE, SCROLLABLE_TYPE } from '../constants';
import type { ScrollableRef, Scrollable } from '../types';

export const useScrollable = (): {
  scrollableRef: RefObject<ScrollableRef>;
  animatedScrollableType: SharedValue<SCROLLABLE_TYPE>;
  animatedScrollableContentOffsetY: SharedValue<number>;
  animatedScrollableOverrideState: SharedValue<SCROLLABLE_STATE>;
  isScrollableRefreshable: SharedValue<boolean>;
  setScrollableRef: (ref: ScrollableRef) => void;
  removeScrollableRef: (ref: RefObject<Scrollable>) => void;
} => {
  // refs
  const scrollableRef = useRef<ScrollableRef>(null);
  const previousScrollableRef = useRef<ScrollableRef>(null);

  // variables
  const animatedScrollableType = useSharedValue<SCROLLABLE_TYPE>(SCROLLABLE_TYPE.UNDETERMINED);
  const animatedScrollableContentOffsetY = useSharedValue<number>(0);
  const animatedScrollableOverrideState = useSharedValue<SCROLLABLE_STATE>(SCROLLABLE_STATE.UNDETERMINED);
  const isScrollableRefreshable = useSharedValue<boolean>(false);

  // callbacks
  const setScrollableRef = useCallback((ref: ScrollableRef) => {
    const currentRefId = scrollableRef.current?.id ?? null;

    if (currentRefId !== ref.id) {
      if (scrollableRef.current) {
        // @ts-ignore
        previousScrollableRef.current = scrollableRef.current;
      }
      // @ts-ignore
      scrollableRef.current = ref;
    }
  }, []);

  const removeScrollableRef = useCallback((ref: RefObject<Scrollable>) => {
    let id;
    try {
      id = findNodeHandle(ref.current);
    } catch {
      return;
    }

    const currentRefId = scrollableRef.current?.id ?? null;

    if (id === currentRefId) {
      // @ts-ignore
      scrollableRef.current = previousScrollableRef.current;
    }
  }, []);

  return {
    scrollableRef,
    animatedScrollableType,
    animatedScrollableContentOffsetY,
    animatedScrollableOverrideState,
    isScrollableRefreshable,
    setScrollableRef,
    removeScrollableRef,
  };
};
